package net.lab0.fractal.fractals.mandelbrot;

import static com.jogamp.opencl.CLMemory.Mem.READ_ONLY;
import static com.jogamp.opencl.CLMemory.Mem.WRITE_ONLY;
import static java.lang.Math.min;
import static java.lang.System.nanoTime;
import static java.lang.System.out;

import java.io.IOException;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import com.jogamp.opencl.CLBuffer;
import com.jogamp.opencl.CLCommandQueue;
import com.jogamp.opencl.CLContext;
import com.jogamp.opencl.CLDevice;
import com.jogamp.opencl.CLKernel;
import com.jogamp.opencl.CLProgram;

public class OpenCLKernel
{
    private int globalWorkSize;
    private CLKernel kernel;
    
    public OpenCLKernel()
    {
        // set up (uses default CLPlatform and creates context for all devices)
        CLContext context = CLContext.create();
        out.println("created " + context);
        
        // always make sure to release the context under all circumstances
        // not needed for this particular sample but recommented
        try
        {
            // select fastest device
            CLDevice device = context.getMaxFlopsDevice();
            out.println("using " + device);
            
            // create command queue on device.
            CLCommandQueue queue = device.createCommandQueue();
            
            int elementCount = 65536; // Length of arrays to process
            int localWorkSize = min(device.getMaxWorkGroupSize(), 256); // Local work size dimensions
            globalWorkSize = roundUp(localWorkSize, elementCount);
            
            // load sources, create and build program
            CLProgram program = context.createProgram(OpenCLMandelbrotComputing.class.getResourceAsStream("programm.cl ")).build();
            
            kernel = program.createCLKernel("f");
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            // cleanup all resources associated with this context.
            context.release();
        }
    }
    
    private int roundUp(int groupSize, int globalSize)
    {
        int r = globalSize % groupSize;
        if (r == 0)
        {
            return globalSize;
        }
        else
        {
            return globalSize + groupSize - r;
        }
    }
}
